#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

uint16_t modbus_slave_reg[200];

#define QX(x,y) ((x*8) + y)                        //0x
#define MX(x,y) ((x*8) + y + 3000)                 //0x
#define IX(x,y) (((x/8) + y + 3000) + 100000)      //1x
#define IW(x)   ((x/2) + 300000)                   //3x
#define MW(x)   (((x/2) + 3000) + 400000)          //4x
#define MD(x)   (((x/2) + 3000) + 400000)          //4x
#define MDF(x)  (((x/2) + 3000) + 400000)          //4x

void set_modbus_word_bit(uint16_t *pWord,uint8_t bit, uint16_t value)
{
    if(value){
        *pWord |= (uint16_t)(1 << bit);
    }else{
        *pWord &= (~(uint16_t)(1 << bit));
    }
}

void set_modbus_word(uint16_t *pWord, uint16_t value)
{
    *pWord = value;
}

void set_modbus_dword(uint16_t *pWord, uint16_t *value)
{
    *pWord++ = *value++;
    *pWord   = *value;
}

void set_modbus_485_holdreg(uint8_t type, uint8_t *data, uint16_t saddr, uint16_t num)
{
    uint32_t addr = 0;
    uint16_t i = 0, *pWord = modbus_slave_reg;
    for(i = 0; i < num; i++){
        switch(type){
            case 0:addr = saddr + i;break;
            case 1:addr = saddr + i + 100000;break;
            case 3:addr = saddr + i + 300000;break;
            case 4:addr = saddr + i + 400000;break;
            default:return;
        }
        switch (addr) {
            /********* word 0 ********/
            case MX(394,6):set_modbus_word_bit(&pWord[0], 0, data[i]);break;//bit0
            case MX(394,7):set_modbus_word_bit(&pWord[0], 1, data[i]);break;//bit1
            case MX(448,2):set_modbus_word_bit(&pWord[0], 2, data[i]);break;//bit2
            case MX(448,3):set_modbus_word_bit(&pWord[0], 3, data[i]);break;//bit3
            case MX(399,0):set_modbus_word_bit(&pWord[0], 4, data[i]);break;//bit4
            case MX(201,2):set_modbus_word_bit(&pWord[0], 5, data[i]);break;//bit5
            case QX(0,0):set_modbus_word_bit(&pWord[0], 6, data[i]);break;//bit6
            case QX(0,4):set_modbus_word_bit(&pWord[0], 7, data[i]);break;//bit7
            case QX(0,5):set_modbus_word_bit(&pWord[0], 8, data[i]);break;//bit8
            case QX(0,6):set_modbus_word_bit(&pWord[0], 9, data[i]);break;//bit9
            case MX(394,3):set_modbus_word_bit(&pWord[0], 10, data[i]);break;//bit10
            case QX(1,0):set_modbus_word_bit(&pWord[0], 11, data[i]);break;//bit11
            case QX(1,1):set_modbus_word_bit(&pWord[0], 12, data[i]);break;//bit12
            case QX(1,2):set_modbus_word_bit(&pWord[0], 13, data[i]);break;//bit13
            //case QX(x,y):set_modbus_word_bit(&pWord[0], 14, data[i]);break;//bit14
            //case QX(x,y):set_modbus_word_bit(&pWord[0], 15, data[i]);break;//bit15
            /********* word 1 ********/
            case MX(202,5):set_modbus_word_bit(&pWord[1], 0, data[i]);break;//bit0
            case MX(202,6):set_modbus_word_bit(&pWord[1], 1, data[i]);break;//bit1
            case MX(202,7):set_modbus_word_bit(&pWord[1], 2, data[i]);break;//bit2
            case MX(393,0):set_modbus_word_bit(&pWord[1], 3, data[i]);break;//bit3
            case MX(393,1):set_modbus_word_bit(&pWord[1], 4, data[i]);break;//bit4
            case MX(393,2):set_modbus_word_bit(&pWord[1], 5, data[i]);break;//bit5
            case MX(393,3):set_modbus_word_bit(&pWord[1], 6, data[i]);break;//bit6
            case MX(393,4):set_modbus_word_bit(&pWord[1], 7, data[i]);break;//bit7
            case MX(393,5):set_modbus_word_bit(&pWord[1], 8, data[i]);break;//bit8
            case MX(393,6):set_modbus_word_bit(&pWord[1], 9, data[i]);break;//bit9
            case MX(393,7):set_modbus_word_bit(&pWord[1], 10, data[i]);break;//bit10
            case MX(394,0):set_modbus_word_bit(&pWord[1], 11, data[i]);break;//bit11
            case MX(394,1):set_modbus_word_bit(&pWord[1], 12, data[i]);break;//bit12
            case MX(394,2):set_modbus_word_bit(&pWord[1], 13, data[i]);break;//bit13
            case MX(395,0):set_modbus_word_bit(&pWord[1], 14, data[i]);break;//bit14
            case MX(396,0):set_modbus_word_bit(&pWord[1], 15, data[i]);break;//bit15
            /********* word 2 ********/
            case MX(396,1):set_modbus_word_bit(&pWord[2], 0, data[i]);break;//bit0
            case MX(396,2):set_modbus_word_bit(&pWord[2], 1, data[i]);break;//bit1
            case MX(396,3):set_modbus_word_bit(&pWord[2], 2, data[i]);break;//bit2
            case MX(396,4):set_modbus_word_bit(&pWord[2], 3, data[i]);break;//bit3
            case MX(396,5):set_modbus_word_bit(&pWord[2], 4, data[i]);break;//bit4
            case MX(396,7):set_modbus_word_bit(&pWord[2], 5, data[i]);break;//bit5
            case MX(397,0):set_modbus_word_bit(&pWord[2], 6, data[i]);break;//bit6
            case MX(397,1):set_modbus_word_bit(&pWord[2], 7, data[i]);break;//bit7
            case MX(397,2):set_modbus_word_bit(&pWord[2], 8, data[i]);break;//bit8
            case MX(397,3):set_modbus_word_bit(&pWord[2], 9, data[i]);break;//bit9
            case MX(397,4):set_modbus_word_bit(&pWord[2], 10, data[i]);break;//bit10
            case MX(398,4):set_modbus_word_bit(&pWord[2], 11, data[i]);break;//bit11
            case MX(399,2):set_modbus_word_bit(&pWord[2], 12, data[i]);break;//bit12
            case MX(399,3):set_modbus_word_bit(&pWord[2], 13, data[i]);break;//bit13
            case MX(399,4):set_modbus_word_bit(&pWord[2], 14, data[i]);break;//bit14
            case MX(399,6):set_modbus_word_bit(&pWord[2], 15, data[i]);break;//bit15
            /********* word 3 ********/
            case MX(201,3):set_modbus_word_bit(&pWord[3], 0, data[i]);break;//bit0
            case MX(201,4):set_modbus_word_bit(&pWord[3], 1, data[i]);break;//bit1
            case MX(201,5):set_modbus_word_bit(&pWord[3], 2, data[i]);break;//bit2
            case MX(201,6):set_modbus_word_bit(&pWord[3], 3, data[i]);break;//bit3
            case MX(201,7):set_modbus_word_bit(&pWord[3], 4, data[i]);break;//bit4
            case MX(202,0):set_modbus_word_bit(&pWord[3], 5, data[i]);break;//bit5
            case MX(202,1):set_modbus_word_bit(&pWord[3], 6, data[i]);break;//bit6
            case MX(202,2):set_modbus_word_bit(&pWord[3], 7, data[i]);break;//bit7
            case MX(202,3):set_modbus_word_bit(&pWord[3], 8, data[i]);break;//bit8
            case MX(202,4):set_modbus_word_bit(&pWord[3], 9, data[i]);break;//bit9
            //case MX(x,y):set_modbus_word_bit(&pWord[3], 10, data[i]);break;//bit10
            //case MX(x,y):set_modbus_word_bit(&pWord[3], 11, data[i]);break;//bit11
            //case MX(x,y):set_modbus_word_bit(&pWord[3], 12, data[i]);break;//bit12
            //case MX(x,y):set_modbus_word_bit(&pWord[3], 13, data[i]);break;//bit13
            //case MX(x,y):set_modbus_word_bit(&pWord[3], 14, data[i]);break;//bit14
            //case MX(x,y):set_modbus_word_bit(&pWord[3], 15, data[i]);break;//bit15
            /********* word 4 ********/
            case IW(4):set_modbus_word(&pWord[4], *(uint16_t *)&data[2*i]);break;
            case IW(6):set_modbus_word(&pWord[5], *(uint16_t *)&data[2*i]);break;
            case IW(8):set_modbus_word(&pWord[6], *(uint16_t *)&data[2*i]);break;
            case IW(10):set_modbus_word(&pWord[7], *(uint16_t *)&data[2*i]);break;
            case IW(12):set_modbus_word(&pWord[8], *(uint16_t *)&data[2*i]);break;
            case IW(14):set_modbus_word(&pWord[9], *(uint16_t *)&data[2*i]);break;
            case IW(16):set_modbus_word(&pWord[10], *(uint16_t *)&data[2*i]);break;
            case IW(18):set_modbus_word(&pWord[10], *(uint16_t *)&data[2*i]);break;
            case MD(356):set_modbus_dword(&pWord[12], (uint16_t *)&data[2*i]);break;
            case MD(460):set_modbus_dword(&pWord[14], (uint16_t *)&data[2*i]);break;
            case MD(472):set_modbus_dword(&pWord[16], (uint16_t *)&data[2*i]);break;
            case MD(476):set_modbus_dword(&pWord[18], (uint16_t *)&data[2*i]);break;
            case MD(486):set_modbus_dword(&pWord[20], (uint16_t *)&data[2*i]);break;
            case MD(708):set_modbus_dword(&pWord[22], (uint16_t *)&data[2*i]);break;
            case MD(712):set_modbus_dword(&pWord[24], (uint16_t *)&data[2*i]);break;
            case MD(716):set_modbus_dword(&pWord[26], (uint16_t *)&data[2*i]);break;
            case MW(458):set_modbus_dword(&pWord[28], (uint16_t *)&data[2*i]);break;
            case MW(760):set_modbus_word(&pWord[29], *(uint16_t *)&data[2*i]);break;
            case MX(448,1):set_modbus_word(&pWord[30], data[i]);break;
            case MX(448,4):set_modbus_word(&pWord[31], data[i]);break;
            case MX(448,5):set_modbus_word(&pWord[32], data[i]);break;
            case MX(394,4):set_modbus_word(&pWord[33], data[i]);break;
            case MX(395,4):set_modbus_word(&pWord[34], data[i]);break;
            case MX(395,7):set_modbus_word(&pWord[35], data[i]);break;
            case MW(402):set_modbus_word(&pWord[36], *(uint16_t *)&data[2*i]);break;
            case MW(404):set_modbus_word(&pWord[37], *(uint16_t *)&data[2*i]);break;
            case MW(414):set_modbus_word(&pWord[38], *(uint16_t *)&data[2*i]);break;
            case MW(416):set_modbus_word(&pWord[39], *(uint16_t *)&data[2*i]);break;
            case MW(420):set_modbus_word(&pWord[40], *(uint16_t *)&data[2*i]);break;
            case MW(428):set_modbus_word(&pWord[41], *(uint16_t *)&data[2*i]);break;
            case MW(430):set_modbus_word(&pWord[42], *(uint16_t *)&data[2*i]);break;
            case MW(780):set_modbus_word(&pWord[43], *(uint16_t *)&data[2*i]);break;
            case MW(782):set_modbus_word(&pWord[44], *(uint16_t *)&data[2*i]);break;
            case MW(784):set_modbus_word(&pWord[45], *(uint16_t *)&data[2*i]);break;
            case MW(418):set_modbus_word(&pWord[46], *(uint16_t *)&data[2*i]);break;
            case MW(306):set_modbus_word(&pWord[47], *(uint16_t *)&data[2*i]);break;
            case MW(308):set_modbus_word(&pWord[48], *(uint16_t *)&data[2*i]);break;
            case MW(640):set_modbus_word(&pWord[49], *(uint16_t *)&data[2*i]);break;
            case MW(642):set_modbus_word(&pWord[50], *(uint16_t *)&data[2*i]);break;
            case MW(644):set_modbus_word(&pWord[51], *(uint16_t *)&data[2*i]);break;
            case MW(646):set_modbus_word(&pWord[52], *(uint16_t *)&data[2*i]);break;
            default:break;
        }
    }
}

uint8_t byte_arry[500];
uint16_t word_arry[500];

int main(void)
{
    uint16_t i = 0, index = 0;
    //0~23
    index = 0;
    for(i = 0; i <= 23; i ++){
        byte_arry[index++] = (i+1)%2;
    }
    set_modbus_485_holdreg(0, byte_arry, 0, (23 - 0 + 1));
    //4608~4628
    index = 0;
    for(i = 4608; i <= 4628; i ++){
        byte_arry[index++] = (i+1)%2;
    }
    set_modbus_485_holdreg(0, byte_arry, 4608, (4628 - 4608 + 1));
    //6144~6215
    index = 0;
    for(i = 6144; i <= 6215; i ++){
        byte_arry[index++] = (i+1)%2;
    }
    set_modbus_485_holdreg(0, byte_arry, 6144, (6215 - 6144 + 1));
    //6585~6587
    index = 0;
    for(i = 6585; i <= 6587; i ++){
        byte_arry[index++] = (i+1)%2;
    }
    set_modbus_485_holdreg(0, byte_arry, 6585, (6587 - 6585 + 1));
    //6588~6589
    index = 0;
    for(i = 6588; i <= 6589; i ++){
        byte_arry[index++] = (i+1)%2;
    }
    set_modbus_485_holdreg(0, byte_arry, 6588, (6589 - 6588 + 1));
    //9048~9052
    index = 0;
    for(i = 9048; i <= 9052; i ++){
        byte_arry[index++] = (i+1)%2;
    }
    set_modbus_485_holdreg(0, byte_arry, 9048, (9052 - 9048 + 1));

    //2~8
    index = 0;
    for(i = 2; i <= 8; i ++){
        word_arry[index++] = i;
    }
    set_modbus_485_holdreg(3, (uint8_t *)word_arry, 2, (8 - 2 + 1));

    //3150~3239
    index = 0;
    for(i = 3150; i <= 3239; i ++){
        word_arry[index++] = i;
    }
    set_modbus_485_holdreg(4, (uint8_t *)word_arry, 3150, (3239 - 3150 + 1));
    //3240~3329
    index = 0;
    for(i = 3240; i <= 3329; i ++){
        word_arry[index++] = i;
    }
    set_modbus_485_holdreg(4, (uint8_t *)word_arry, 3240, (3329 - 3240 + 1));
    //3330~3399
    index = 0;
    for(i = 3330; i <= 3399; i ++){
        word_arry[index++] = i;
    }
    set_modbus_485_holdreg(4, (uint8_t *)word_arry, 3330, (3399 - 3330 + 1));
    return 0;
}
